home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Best of www.BestZips.com (Collector's Edition)
/
Best of WWW.BESTZIPS.COM Collector's Edition (JCSM Shareware) (JCS Marketing).ISO
/
internet
/
zannetb1.zip
/
Zanserv.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-12-15
|
60KB
|
2,461 lines
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <memory.h>
#include <sys/types.h>
#include <dirent.h>
#include <fcntl.h>
#include <utime.h>
#include "zanserv.h"
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
void ConnectToWindows ();
void ProcessMessages ();
void fsConfigure ();
void fsOpenFile ();
void fsCloseFile ();
void fsReadFile ();
void fsWriteFile ();
void fsFileSeek ();
void fsFindFirstFile ();
void fsFindNextFile ();
void fsFindClose ();
void fsFileAttributes ();
void fsDir ();
void fsDeleteFile ();
void fsRenameFile ();
void fsGetDiskInfo ();
void fsWriteMoveEOF ();
void ProcessDir ();
int MakeNativePath ();
int readn ();
int writen ();
int MetaMatch ();
int MatchStarsAndQMs ();
int FindSubPattern ();
int CheckForExtension ();
int CaseMatchDirectory ();
char *zstrupr ();
char *StripFileFromPath ();
int FindSubPattern ();
void NukeDotStar ();
USHORT MapWindowsError ();
int SetFilePosition ();
char ProgramName[256];
char HomePath[MAX_PATH];
ULONG ulMaxReaddirs = ZANNET_MAX_READDIRS;
ULONG ulDefaultAttributes = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
int fDebug = TRUE;
char InBuff[ZANSERV_IN_BUFFER_SIZE];
char OutBuff[ZANSERV_OUT_BUFFER_SIZE];
char NativeSlash = '/';
char NativeSlashStr[] = "/";
char WindowsBSlash = '\\';
USHORT WindowsErrors[ESTALE+1] =
{
NO_ERROR, /* SUCCESS */
ERROR_INVALID_FUNCTION, /* EPERM 1 Operation not permitted */
ERROR_FILE_NOT_FOUND, /* ENOENT 2 No such file or directory */
ERROR_INVALID_FUNCTION, /* ESRCH 3 No such process */
ERROR_UNEXP_NET_ERR, /* EINTR 4 interrupted system call */
ERROR_UNEXP_NET_ERR, /* EIO 5 I/O error */
ERROR_UNEXP_NET_ERR, /* ENXIO 6 No such device or address */
ERROR_UNEXP_NET_ERR, /* E2BIG 7 Arg list too long */
ERROR_UNEXP_NET_ERR, /* ENOEXEC 8 Exec format error */
ERROR_INVALID_HANDLE, /* EBADF 9 Bad file descriptor */
ERROR_UNEXP_NET_ERR, /* ECHILD 10 No child processes */
ERROR_DEV_NOT_EXIST, /* EAGAIN 11 Resource temporarily unavailable */
ERROR_DISK_FULL, /* ENOMEM 12 Not enough space */
ERROR_ACCESS_DENIED, /* EACCES 13 Permission denied */
ERROR_INVALID_ADDRESS, /* EFAULT 14 Bad address */
ERROR_UNEXP_NET_ERR, /* ENOTBLK 15 Block device required */
ERROR_NETWORK_BUSY, /* EBUSY 16 Resource busy */
ERROR_FILE_EXISTS, /* EEXIST 17 File exists */
ERROR_UNEXP_NET_ERR, /* EXDEV 18 Improper link */
ERROR_UNEXP_NET_ERR, /* ENODEV 19 No such device */
ERROR_DIRECTORY, /* ENOTDIR 20 Not a directory */
ERROR_DIR_NOT_EMPTY, /* EISDIR 21 Is a directory */
ERROR_BAD_ARGUMENTS, /* EINVAL 22 Invalid argument */
ERROR_TOO_MANY_OPEN_FILES, /* ENFILE 23 Too many open files in system */
ERROR_TOO_MANY_OPEN_FILES, /* EMFILE 24 Too many open files */
ERROR_UNEXP_NET_ERR, /* ENOTTY 25 Inappropriate I/O control operation */
ERROR_NETWORK_BUSY, /* ETXTBSY 26 Text file busy */
ERROR_DISK_FULL, /* EFBIG 27 File too large */
ERROR_DISK_FULL, /* ENOSPC 28 No space left on device */
ERROR_SEEK_ON_DEVICE, /* ESPIPE 29 Invalid seek */
ERROR_ACCESS_DENIED, /* EROFS 30 Read only file system */
ERROR_UNEXP_NET_ERR, /* EMLINK 31 Too many links */
ERROR_BROKEN_PIPE, /* EPIPE 32 Broken pipe */
ERROR_UNEXP_NET_ERR, /* EDOM 33 Domain error within math function */
ERROR_UNEXP_NET_ERR, /* ERANGE 34 Result too large */
ERROR_UNEXP_NET_ERR, /* ENOMSG 35 No message of desired type */
ERROR_UNEXP_NET_ERR, /* EIDRM 36 Identifier removed */
ERROR_UNEXP_NET_ERR, /* ECHRNG 37 Channel number out of range */
ERROR_UNEXP_NET_ERR, /* EL2NSYNC 38 Level 2 not synchronized */
ERROR_UNEXP_NET_ERR, /* EL3HLT 39 Level 3 halted */
ERROR_UNEXP_NET_ERR, /* EL3RST 40 Level 3 reset */
ERROR_UNEXP_NET_ERR, /* ELNRNG 41 Link number out of range */
ERROR_UNEXP_NET_ERR, /* EUNATCH 42 Protocol driver not attached */
ERROR_UNEXP_NET_ERR, /* ENOCSI 43 No CSI structure available */
ERROR_UNEXP_NET_ERR, /* EL2HLT 44 Level 2 halted */
ERROR_POSSIBLE_DEADLOCK, /* EDEADLK 45 Resource deadlock avoided */
ERROR_NOT_READY, /* ENOTREADY 46 Device not ready */
ERROR_WRITE_PROTECT, /* EWRPROTECT 47 Write-protected media */
ERROR_NOT_DOS_DISK, /* EFORMAT 48 Unformatted media */
ERROR_LOCK_VIOLATION, /* ENOLCK 49 No locks available */
ERROR_UNEXP_NET_ERR, /* ENOCONNECT 50 no connection */
0, /* nothing 51 */
ERROR_NOT_DOS_DISK /* ESTALE 52 no filesystem */
};
main (argc, argv)
int argc;
char *argv[];
{
char hostIP[64];
char hostName[MAX_PATH];
struct hostent *pHostEntry;
int port, sockfd;
struct in_addr *pHostAddr;
char *pEnv;
/* First argument is IP address and second is port */
if (argc != 3)
{
printf ("\nUsage: %s <IP Address> <Port>\n\n", argv[0]);
gethostname (hostName, sizeof(hostName));
printf ("This machine's host name is: %s\n", hostName);
if (pHostEntry = gethostbyname (hostName))
{
pHostAddr = (struct in_addr *)pHostEntry->h_addr;
printf ("This machine's IP address is: %s\n\n", inet_ntoa(*pHostAddr));
}
exit (1);
}
strcpy (ProgramName, argv[0]);
strcpy (hostIP, argv[1]);
port = atoi (argv[2]);
ConnectToWindows (hostIP, port, &sockfd);
/* Don't change the below "CONNECT!" string....Windows looks for it!!!! */
printf ("%s\n", ZANNET_CONNECT_STRING);
fflush (stdout);
/* Set default home path */
if (pEnv = (char *)getenv("HOME"))
strcpy (HomePath, pEnv);
else
strcpy (HomePath, "/");
/* We handle all permission bits so turn off file creation mask */
umask (~(S_IRWXU | S_IRWXG | S_IRWXO));
ProcessMessages (sockfd);
return 0;
}
/*
* Connect to the Windows 95 machine
*/
void ConnectToWindows (hostIP, port, sockfd)
char hostIP[];
int port;
int *sockfd;
{
struct sockaddr_in serv_addr;
/* Open the socket */
memset ((char *)&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = inet_addr (hostIP);
serv_addr.sin_port = htons (port);
if ((*sockfd = socket (AF_INET, SOCK_STREAM, 0)) < 0)
{
!fDebug ? 0 : printf ("%s Socket Error: socket(), rc = %d\n", ProgramName, errno);
exit (1);
}
/* Connect to Windows Server */
if (connect (*sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
{
!fDebug ? 0 : printf ("%s Socket Error: connect(), port = %d, rc = %d, ip = %s\n",
ProgramName, port, errno, hostIP);
exit (1);
}
}
/*
* Process Windows file system commands
*/
void ProcessMessages (sockfd)
int sockfd;
{
winio_generic *pwinGen;
int iBytesRead;
pwinGen = (winio_generic *)InBuff;
while (iBytesRead = readn(sockfd, pwinGen, sizeof(winio_generic)))
{
/* First read the generic packet (above) and get the length */
if (iBytesRead < sizeof(winio_generic))
{
!fDebug ? 0 : printf ("%s error. First readn() = %d\n", iBytesRead);
exit (1);
}
pwinGen->usType = ntohs(pwinGen->usType);
pwinGen->usLen = ntohs(pwinGen->usLen);
pwinGen->ulFlags = ntohl(pwinGen->ulFlags);
/*
!fDebug ? 0 : printf ("Got Generic, type = %d, reading len = %d\n",
pwinGen->usType, (int)(pwinGen->usLen - sizeof(winio_generic)));
*/
/* Now read the full packet */
iBytesRead = readn (sockfd, &InBuff[sizeof(winio_generic)],
pwinGen->usLen - sizeof(winio_generic));
if (iBytesRead < (pwinGen->usLen - sizeof(winio_generic)))
{
!fDebug ? 0 : printf ("%s error. Second readn() = %d\n", iBytesRead);
exit (1);
}
switch (pwinGen->usType)
{
case FS_CONFIGURE:
fsConfigure (sockfd, InBuff);
break;
case FS_OPENFILE:
fsOpenFile (sockfd, InBuff);
break;
case FS_CLOSEFILE:
fsCloseFile (sockfd, InBuff);
break;
case FS_READFILE:
fsReadFile (sockfd, InBuff);
break;
case FS_WRITEFILE:
fsWriteFile (sockfd, InBuff);
break;
case FS_FILESEEK:
fsFileSeek (sockfd, InBuff);
break;
case FS_FINDFIRSTFILE:
fsFindFirstFile (sockfd, InBuff);
break;
case FS_FINDNEXTFILE:
fsFindNextFile (sockfd, InBuff);
break;
case FS_FINDCLOSE:
fsFindClose (sockfd, InBuff);
break;
case FS_FILEATTRIBUTES:
fsFileAttributes (sockfd, InBuff);
break;
case FS_DIR:
fsDir (sockfd, InBuff);
break;
case FS_DELETEFILE:
fsDeleteFile (sockfd, InBuff);
break;
case FS_RENAMEFILE:
fsRenameFile (sockfd, InBuff);
break;
case FS_GETDISKINFO:
fsGetDiskInfo (sockfd, InBuff);
break;
default:
!fDebug ? 0 : printf ("%s Unknown Command: Command = %d\n", pwinGen->usType);
}
}
}
/*
* Configuration and shutdown
*/
void fsConfigure (sockfd, pInBuff)
int sockfd;
char *pInBuff;
{
fs_configure *pConfig;
fs_configureAck *pConfigAck;
struct stat fStat;
USHORT usLen;
pConfigAck = (fs_configureAck *)OutBuff;
memset ((char *)pConfigAck, 0, sizeof(fs_configureAck));
pConfigAck->usVersionMajor = htons(ZANNET_VERSION_MAJOR);
pConfigAck->usVersionMinor = htons(ZANNET_VERSION_MINOR);
pConfig = (fs_configure *)pInBuff;
pConfig->ulServerDefaultAttribs = ntohl(pConfig->ulServerDefaultAttribs);
pConfig->ulMaxReaddirs = ntohl(pConfig->ulMaxReaddirs);
pConfig->sPathLen = ntohs(pConfig->sPathLen);
!fDebug ? 0 : printf ("FS_CONFIGURE: \n");
if (pConfig->ulFlags & ZANSERV_DEBUG_ON)
{
fDebug = TRUE;
!fDebug ? 0 : printf ("Debug On!\n");
}
if (pConfig->ulFlags & ZANSERV_DEBUG_OFF)
{
!fDebug ? 0 : printf ("Debug Off!\n");
fDebug = FALSE;
}
if (pConfig->ulFlags & ZANSERV_MAX_READDIRS)
{
!fDebug ? 0 : printf ("ZANSERV_MAX_READDIRS = %d\n", pConfig->ulMaxReaddirs);
fflush(stdout);
ulMaxReaddirs = pConfig->ulMaxReaddirs;
}
if (pConfig->ulFlags & ZANSERV_NEW_HOME)
{
!fDebug ? 0 : printf ("ZANSERV_NEW_HOME: %s\n", pConfig->HomePath);
if (!stat(pConfig->HomePath, &fStat))
{
strcpy (HomePath, pConfig->HomePath);
}
else
{
pConfigAck->rc = ERROR_FILE_NOT_FOUND;
!fDebug ? 0 : printf ("***** Can't find new home directory: %s\n", pConfig->HomePath);
}
}
if (pConfig->ulFlags & ZANSERV_ATTRIBS)
{
!fDebug ? 0 : printf ("ZANSERV_ATTRIBS: %x\n", pConfig->ulServerDefaultAttribs);
ulDefaultAttributes = pConfig->ulServerDefaultAttribs;
}
/* Write the results to Windows */
if (pConfig->ulFlags & ZANSERV_PING)
{
usLen = pConfig->usLen;
!fDebug ? 0 : printf ("ZANSERV_PING: Sending %d bytes\n", usLen);
memcpy (&OutBuff[sizeof(fs_configureAck)], pConfig->HomePath, usLen);
}
else
usLen = sizeof(fs_configureAck);
pConfigAck->usLen = htons(usLen);
pConfigAck->usType = htons(pConfig->usType);
pConfigAck->rc = htonl(pConfigAck->rc);
pConfigAck->ulKey = pConfig->ulKey;
/* Shutdown if requested. This is ACKed by the Windows socket disconnect */
if (pConfig->ulFlags & ZANSERV_SHUTDOWN)
{
!fDebug ? 0 : printf ("Normal Shutdown with flag: ZANSERV_SHUTDOWN\n");
close (sockfd);
exit (0);
}
writen (sockfd, pConfigAck, usLen);
!fDebug ? 0 : printf ("FS_CONFIGURE: rc=%d\n", ntohl(pConfigAck->rc));
}
/*
* Open file
*/
void fsOpenFile (sockfd, pInBuff)
int sockfd;
char *pInBuff;
{
fs_openfile *pOpen;
fs_openfileAck *pOpenAck;
struct stat fStat;
int iflags = 0;
mode_t mode = 0;
char NATIVEPath[MAX_PATH];
pOpen = (fs_openfile *)pInBuff;
pOpen->ulAttribs = ntohl(pOpen->ulAttribs);
pOpen->usOptions = ntohs(pOpen->usOptions);
pOpen->sPathLen = ntohs(pOpen->sPathLen);
!fDebug ? 0 : printf ("FS_OPENFILE: Flags=%x, Attribs=%x, Options=%x, Path=%s\n",
pOpen->ulFlags, pOpen->ulAttribs, pOpen->usOptions, pOpen->Path);
pOpenAck = (fs_openfileAck *)OutBuff;
memset ((char *)pOpenAck, 0, sizeof(fs_openfileAck));
/* Translate Windows flags to POSIX */
switch (pOpen->ulFlags & ACCESS_MODE_MASK)
{
case ACCESS_READONLY:
iflags |= O_RDONLY;
break;
case ACCESS_WRITEONLY:
iflags |= O_WRONLY;
break;
case ACCESS_READWRITE:
iflags |= O_RDWR;
break;
case ACCESS_EXECUTE:
iflags |= O_RDONLY;
break;
default:
iflags |= O_RDONLY;
}
/***
Sharing flags are NOT yet supported. All files are considered
read/write shareable at this time - 11/21/96
switch (pOpen->ulFlags & SHARE_MODE_MASK)
{
case SHARE_COMPATIBILITY:
break;
case SHARE_DENYREADWRITE:
break;
case SHARE_DENYWRITE:
break;
case SHARE_DENYREAD:
break;
default:
}
***/
/* Get the path squared away */
if (pOpenAck->rc = MakeNativePath (pOpen->Path, NATIVEPath, pOpen->ulAttribs))
goto ExitfsOpenFile;
/* Next are the Windows options. Note: mode is ignored if file already
exists! */
switch (pOpen->usOptions & ACTION_MASK)
{
case ACTION_CREATEALWAYS:
{
/* Create a new file. If the file already exists open it and set
its new length and attributes */
iflags |= O_CREAT | O_TRUNC;
if (pOpen->ulAttribs & FILE_ATTRIBUTE_READONLY)
mode = ulDefaultAttributes & ~(S_IWUSR | S_IWGRP | S_IWOTH);
else
mode = ulDefaultAttributes;
if (!(stat(NATIVEPath, &fStat)))
{
/* File already exists, set new attributes */
if (chmod (NATIVEPath, mode) < 0)
{
pOpenAck->rc = MapWindowsError (errno);
}
else
pOpenAck->usAction = ACTION_OPENED;
mode = 0;
}
else
pOpenAck->usAction = ACTION_CREATED;
break;
}
case ACTION_OPENALWAYS:
{
/* Open an existing file. If the file does not exist, create a new file */
if (stat(NATIVEPath, &fStat))
{
/* No existing file, set mode for file creation */
if (pOpen->ulAttribs & FILE_ATTRIBUTE_READONLY)
mode = ulDefaultAttributes & ~(S_IWUSR | S_IWGRP | S_IWOTH);
else
mode = ulDefaultAttributes;
pOpenAck->usAction = ACTION_CREATED;
}
else
pOpenAck->usAction = ACTION_OPENED;
iflags |= O_CREAT;
break;
}
case ACTION_CREATENEW:
{
/* Create a new file. Fail if the file already exists */
if (pOpen->ulAttribs & FILE_ATTRIBUTE_READONLY)
mode = ulDefaultAttributes & ~(S_IWUSR | S_IWGRP | S_IWOTH);
else
mode = ulDefaultAttributes;
iflags |= O_CREAT | O_EXCL;
pOpenAck->usAction = ACTION_CREATED;
break;
}
case ACTION_REPLACEEXISTING:
{
/* Open an existing file and set its new length. Fail if the file does not exist */
iflags |= O_TRUNC;
if (stat(NATIVEPath, &fStat))
{
/* No existing file, set error */
pOpenAck->rc = ERROR_FILE_NOT_FOUND;
}
else
pOpenAck->usAction = ACTION_REPLACED;
break;
}
case ACTION_OPENEXISTING:
{
/* Open an existing file. Fail if the file does not exist */
pOpenAck->usAction = ACTION_OPENED;
break;
}
default:
{
/* Open an existing file. Fail if the file does not exist */
pOpenAck->usAction = ACTION_OPENED;
break;
}
}
/* Make sure this is not a directory */
if (!stat(NATIVEPath, &fStat))
{
if (S_ISDIR(fStat.st_mode))
pOpenAck->rc = ERROR_ACCESS_DENIED;
}
if (!pOpenAck->rc)
{
if (mode)
pOpenAck->iFileHandle = open (NATIVEPath, iflags, mode);
else
pOpenAck->iFileHandle = open (NATIVEPath, iflags);
if (pOpenAck->iFileHandle > 0)
{
/* Get the length, last modification date/time and attributes */
if (!(stat(NATIVEPath, &fStat)))
{
pOpenAck->ulSize = fStat.st_size;
pOpenAck->LastAccess = fStat.st_mtime;
if ((fStat.st_mode & S_IRUSR) && !(fStat.st_mode & S_IWUSR))
{
/* !fDebug ? 0 : printf ("Open file as read only\n"); */
pOpenAck->ulAttribs = FILE_ATTRIBUTE_READONLY;
}
else
{
/* !fDebug ? 0 : printf ("Open file normal\n"); */
/* pOpenAck->ulAttribs = FILE_ATTRIBUTE_ARCHIVE; */
pOpenAck->ulAttribs = 0;
}
}
else
{
pOpenAck->usAction = 0;
pOpenAck->rc = MapWindowsError (errno);
}
}
else
{
pOpenAck->usAction = 0;
pOpenAck->rc = MapWindowsError (errno);
}
}
ExitfsOpenFile:
/* Write the results to Windows */
pOpenAck->ulFlags = htonl(pOpenAck->ulFlags);
pOpenAck->ulAttribs = htonl(pOpenAck->ulAttribs);
pOpenAck->LastAccess = htonl(pOpenAck->LastAccess);
pOpenAck->ulSize = htonl(pOpenAck->ulSize);
pOpenAck->rc = htons(pOpenAck->rc);
pOpenAck->usAction = htons(pOpenAck->usAction);
pOpenAck->usLen = htons(sizeof(fs_openfileAck));
pOpenAck->usType = htons(pOpen->usType);
pOpenAck->ulKey = pOpen->ulKey;
writen (sockfd, pOpenAck, sizeof(fs_openfileAck));
!fDebug ? 0 : printf ("FS_OPENFILE: rc=%d, action=%d, size=%d, attrib=%x\n",
htons(pOpenAck->rc), htons(pOpenAck->usAction), htonl(pOpenAck->ulSize),
htonl(pOpenAck->ulAttribs));
}
/*
* Close file
*/
void fsCloseFile (sockfd, pInBuff)
int sockfd;
char *pInBuff;
{
fs_close *pClose;
fs_closeAck *pCloseAck;
pClose = (fs_close *)pInBuff;
!fDebug ? 0 : printf ("FS_CLOSEFILE: Handle=%d\n", pClose->iFileHandle);
pCloseAck = (fs_closeAck *)OutBuff;
memset ((char *)pCloseAck, 0, sizeof(fs_closeAck));
if (close (pClose->iFileHandle) < 0)
pCloseAck->rc = MapWindowsError (errno);
pCloseAck->usLen = htons(sizeof(fs_closeAck));
pCloseAck->usType = htons(pClose->usType);
pCloseAck->ulKey = pClose->ulKey;
pCloseAck->rc = htons(pCloseAck->rc);
writen (sockfd, pCloseAck, sizeof(fs_closeAck));
!fDebug ? 0 : printf ("FS_CLOSEFILE: rc=%d\n", ntohs(pCloseAck->rc));
}
/*
* Read file
*/
void fsReadFile (sockfd, pInBuff)
int sockfd;
char *pInBuff;
{
fs_readfile *pRead;
fs_readfileAck *pReadAck;
USHORT usWriteLen;
pRead = (fs_readfile *)pInBuff;
pRead->iLength = ntohl(pRead->iLength);
pRead->lPosition = ntohl(pRead->lPosition);
!fDebug ? 0 : printf ("FS_READFILE: Handle=%d, Length=%d, Position=%d\n",
pRead->iFileHandle, pRead->iLength, pRead->lPosition);
pReadAck = (fs_readfileAck *)OutBuff;
memset ((char *)pReadAck, 0, sizeof(fs_readfileAck));
/* Make sure we are in the correct position */
pReadAck->rc = SetFilePosition (pRead->iFileHandle, pRead->lPosition);
if (!pReadAck->rc)
{
pReadAck->lPosition = pRead->lPosition;
/* Do the NATIVE file read */
pReadAck->iLength = readn (pRead->iFileHandle, pReadAck->Data, pRead->iLength);
if (pReadAck->iLength < 0)
{
pReadAck->rc = MapWindowsError (errno);
pReadAck->iLength = 0;
}
else
pReadAck->lPosition += pReadAck->iLength;
}
/* Write the packet and data to Windows */
usWriteLen = sizeof(fs_readfileAck) + pReadAck->iLength - sizeof(pReadAck->Data);
pReadAck->usLen = htons(usWriteLen);
pReadAck->ulKey = pRead->ulKey;
pReadAck->usType = htons(pRead->usType);
pReadAck->iLength = htonl(pReadAck->iLength);
pReadAck->lPosition = htonl(pReadAck->lPosition);
pReadAck->rc = htons(pReadAck->rc);
writen (sockfd, pReadAck, usWriteLen);
!fDebug ? 0 : printf ("FS_READFILE: rc=%d, len=%d, pos=%d\n",
ntohs(pReadAck->rc), ntohl(pReadAck->iLength), ntohl(pReadAck->lPosition));
}
/*
* Write file
*/
void fsWriteFile (sockfd, pInBuff)
int sockfd;
char *pInBuff;
{
fs_writefile *pWrite;
fs_writefileAck *pWriteAck;
pWrite = (fs_writefile *)pInBuff;
pWrite->iLength = ntohl(pWrite->iLength);
pWrite->lPosition = ntohl(pWrite->lPosition);
!fDebug ? 0 : printf ("FS_WRITEFILE: Handle=%d, Length=%d, Position=%d\n",
pWrite->iFileHandle, pWrite->iLength, pWrite->lPosition);
pWriteAck = (fs_writefileAck *)OutBuff;
memset ((char *)pWriteAck, 0, sizeof(fs_writefileAck));
if (!pWrite->iLength)
pWriteAck->rc = ERROR_BAD_ARGUMENTS;
if (pWrite->ulFlags & ZANSERV_FSWRITE_MOVE_EOF && !pWriteAck->rc)
{
fsWriteMoveEOF (pWrite, pWriteAck);
}
else if (!pWriteAck->rc)
{
/* Make sure we are in the correct position */
pWriteAck->rc = SetFilePosition (pWrite->iFileHandle, pWrite->lPosition);
if (!pWriteAck->rc)
{
pWriteAck->lPosition = pWrite->lPosition;
/* Do the NATIVE file write */
pWriteAck->iBytesWritten = writen (pWrite->iFileHandle, pWrite->WriteData, pWrite->iLength);
if (pWriteAck->iBytesWritten < 0)
pWriteAck->rc = MapWindowsError (errno);
else
pWriteAck->lPosition += pWriteAck->iBytesWritten;
}
}
/* Return status to Windows */
pWriteAck->rc = htons(pWriteAck->rc);
pWriteAck->usLen = htons(sizeof(fs_writefileAck));
pWriteAck->ulKey = pWrite->ulKey;
pWriteAck->usType = htons(pWrite->usType);
pWriteAck->iBytesWritten = htonl(pWriteAck->iBytesWritten);
pWriteAck->lPosition = htonl(pWriteAck->lPosition);
writen (sockfd, pWriteAck, sizeof(fs_writefileAck));
!fDebug ? 0 : printf ("FS_WRITEFILE: rc=%d, len=%d, pos=%d\n",
ntohs(pWriteAck->rc), ntohl(pWriteAck->iBytesWritten), ntohl(pWriteAck->lPosition));
}
/*
* fsWriteMoveEOF
*/
void fsWriteMoveEOF (pWrite, pWriteAck)
fs_writefile *pWrite;
fs_writefileAck *pWriteAck;
{
struct stat fStat;
char WritePad[0xFFFF];
char NATIVEPath[MAX_PATH];
char TmpFileName[MAX_PATH];
int lPos=0, lWritten=0, lDiff, lRead=0;
FILE *fpNew, *fpOld;
int NewDesc1, NewDesc2;
/* A zero length write is used by Windows to set a new
EOF position. A real PintheA for us here. Just do it! */
if (!(fstat (pWrite->iFileHandle, &fStat)))
{
if ((fStat.st_mode & S_IRUSR) && !(fStat.st_mode & S_IWUSR))
{
pWriteAck->rc = ERROR_ACCESS_DENIED;
return;
}
if (fStat.st_size > pWrite->lPosition)
{
/* A truncation request, copy the file up to new EOF */
close (pWrite->iFileHandle);
MakeNativePath (pWrite->WriteData, NATIVEPath, pWrite->ulFlags);
!fDebug ? 0 : printf ("FS_WRITEFILE: Truncation - path = %s\n", NATIVEPath);
/* Rename it to something unique */
strcpy (TmpFileName, NATIVEPath);
strcat (TmpFileName, "_ZNet");
if (rename (NATIVEPath, TmpFileName))
{
pWriteAck->rc = MapWindowsError (errno);
}
else
{
/* Open new file and old file as streams */
if (!(fpNew = fopen (NATIVEPath, "w+")))
{
pWriteAck->rc = MapWindowsError (errno);
}
else
{
if (!(fpOld = fopen (TmpFileName, "r")))
{
fclose (fpNew);
pWriteAck->rc = MapWindowsError (errno);
}
else
{
/* Copy up to the new EOF */
while (lPos < pWrite->lPosition)
{
lDiff = pWrite->lPosition - lPos;
lRead = fread (WritePad, 1, lDiff < sizeof(WritePad) ? lDiff : sizeof(WritePad), fpOld);
if (lRead < 0)
{
pWriteAck->rc = MapWindowsError (errno);
break;
}
lWritten = fwrite (WritePad, 1, lRead, fpNew);
if (lWritten < 0)
{
pWriteAck->rc = MapWindowsError (errno);
break;
}
else
lPos += lWritten;
}
/* Close the streams */
fclose (fpOld);
fclose (fpNew);
/* Set the orginal file mode */
chmod (NATIVEPath, fStat.st_mode);
if (!pWriteAck->rc)
{
/* Delete the tmp file */
unlink (TmpFileName);
/* Get back our original file descriptor or else Windows will have a cow */
if ((NewDesc1 = open (NATIVEPath, O_RDWR)) < 0)
{
pWriteAck->rc = MapWindowsError (errno);
}
else if (NewDesc1 != pWrite->iFileHandle)
{
if ((NewDesc2 = fcntl(NewDesc1, F_DUPFD, pWrite->iFileHandle)) < 0)
{
pWriteAck->rc = MapWindowsError (errno);
}
else if (NewDesc2 != pWrite->iFileHandle)
{
pWriteAck->rc = ERROR_WRITE_FAULT;
close (NewDesc2);
}
close (NewDesc1);
}
}
}
}
}
if (!pWriteAck->rc)
pWriteAck->lPosition = pWrite->lPosition;
}
else
{
!fDebug ? 0 : printf ("FS_WRITEFILE: Expansion\n");
/* Grow the file */
memset (WritePad, 0, sizeof(WritePad));
if ((lPos = lseek (pWrite->iFileHandle, 0, SEEK_END)) < 0)
pWriteAck->rc = MapWindowsError (errno);
else
{
while (lPos < pWrite->lPosition)
{
lDiff = pWrite->lPosition - lPos;
lWritten = writen (pWrite->iFileHandle, WritePad, lDiff < sizeof(WritePad) ? lDiff : sizeof(WritePad));
if (lWritten < 0)
{
!fDebug ? 0 : printf ("FS_WRITEFILE: error = %d\n", errno);
pWriteAck->rc = MapWindowsError (errno);
break;
}
else
lPos += lWritten;
}
if (!pWriteAck->rc)
pWriteAck->lPosition = lPos;
}
}
}
else
pWriteAck->rc = ERROR_INVALID_HANDLE;
}
/*
* Seek file - Note: A "seek" is really meaningless because all reads and writes
* come with length and offset. Just return the proper file size. The
* seek is performed on the server for the sake of error checking. FILE_BEGIN
* will never even get here because it is handled in Windows only.
*/
void fsFileSeek (sockfd, pInBuff)
int sockfd;
char *pInBuff;
{
fs_fileseek *pSeek;
fs_fileseekAck *pSeekAck;
int iwhence = -1, DoSeek=TRUE;
struct stat fStat;
pSeek = (fs_fileseek *)pInBuff;
pSeek->lSeekOffset = ntohl(pSeek->lSeekOffset);
!fDebug ? 0 : printf ("FS_FILESEEK: Handle=%d, Flags=%d, Offset=%d\n",
pSeek->iFileHandle, pSeek->ulFlags, pSeek->lSeekOffset);
pSeekAck = (fs_fileseekAck *)OutBuff;
memset ((char *)pSeekAck, 0, sizeof(fs_fileseekAck));
if (fstat(pSeek->iFileHandle, &fStat) < 0)
pSeekAck->rc = MapWindowsError(errno);
if (pSeek->ulFlags == FILE_BEGIN)
{
iwhence = SEEK_SET;
}
else if (pSeek->ulFlags == FILE_END)
{
if ((fStat.st_size + pSeek->lSeekOffset) < 0)
{
DoSeek = FALSE;
pSeekAck->lSeekOffset = fStat.st_size + pSeek->lSeekOffset;
}
iwhence = SEEK_END;
}
else
pSeekAck->rc = ERROR_SEEK_ON_DEVICE;
if (!pSeekAck->rc)
{
if (DoSeek)
{
pSeekAck->lSeekOffset = lseek (pSeek->iFileHandle, pSeek->lSeekOffset, iwhence);
if (pSeekAck->lSeekOffset < 0)
pSeekAck->rc = MapWindowsError (errno);
}
}
pSeekAck->usLen = htons(sizeof(fs_fileseekAck));
pSeekAck->ulKey = pSeek->ulKey;
pSeekAck->usType = htons(pSeek->usType);
pSeekAck->lSeekOffset = htonl(pSeekAck->lSeekOffset);
pSeekAck->rc = htons(pSeekAck->rc);
writen (sockfd, pSeekAck, sizeof(fs_fileseekAck));
!fDebug ? 0 : printf ("FS_FILESEEK: rc=%d, offset=%d\n",
ntohs(pSeekAck->rc), ntohl(pSeekAck->lSeekOffset));
}
/*
* fsFindFirstFile
*/
void fsFindFirstFile (sockfd, pInBuff)
int sockfd;
char *pInBuff;
{
fs_findfirstfile *pFFirst;
fs_findfirstfileAck *pFFirstAck;
DIR *pDir=0;
char NATIVEPath[MAX_PATH];
fs_findfileinfo *pffInfo=0;
char *pSearchPattern=0, *pFile=0;
int isRoot=FALSE;
USHORT usWriteLen;
/* Read the find first structure */
pFFirst = (fs_findfirstfile *)pInBuff;
pFFirst->ulRetBufLen = ntohl(pFFirst->ulRetBufLen);
pFFirst->sPathLen = ntohs(pFFirst->sPathLen);
pFFirst->ulAttrib &= ~FILE_FLAG_KEEP_CASE;
!fDebug ? 0 : printf ("FS_FINDFIRSTFILE: Attribs=%x, BuffLen=%d, Path=%s\n",
pFFirst->ulAttrib, pFFirst->ulRetBufLen, pFFirst->Path);
pFFirstAck = (fs_findfirstfileAck *)OutBuff;
memset ((char *)pFFirstAck, 0, sizeof(fs_findfirstfileAck));
if (pFFirst->ulAttrib & FILE_FLAG_WILDCARDS || pFFirst->ulAttrib & FILE_FLAG_HAS_STAR)
{
/* This is a search pattern - strip it */
/* !fDebug ? 0 : printf ("Found wildcard chars\n"); */
pSearchPattern = StripFileFromPath (pFFirst->Path, WindowsBSlash);
if (!pFFirst->Path[0])
{
/* !fDebug ? 0 : printf ("isRoot = TRUE\n"); */
isRoot = TRUE;
}
}
if (!(pFFirstAck->rc = MakeNativePath (pFFirst->Path, NATIVEPath, pFFirst->ulAttrib)))
{
if (!pSearchPattern)
{
/* The last path element is a file/directory with no wildcards.
Just do a stat on it and return the results */
/* !fDebug ? 0 : printf ("FF on single file: %s\n", NATIVEPath); */
pffInfo = (fs_findfileinfo *)((char *)&pFFirstAck->FindFiles);
if (!(pFFirstAck->rc = FillFileStatus (NATIVEPath, pffInfo)))
{
pFFirstAck->sNumberOfFiles = 1;
/* !fDebug ? 0 : printf ("NATIVEPath = %s\n", NATIVEPath); */
if (pFile = StripFileFromPath (NATIVEPath, NativeSlash))
{
pffInfo->sFileNameLen = strlen(pFile) + 1;
strcpy (pffInfo->FileName, pFile);
}
pFFirstAck->ulRetBufLen = (sizeof(fs_findfileinfo) +
pffInfo->sFileNameLen - sizeof(pffInfo->FileName));
pffInfo->sFileNameLen = htons(pffInfo->sFileNameLen);
/* !fDebug ? 0 : printf ("pFile = %s\n", pFile); */
pFFirstAck->rc = ERROR_NO_MORE_FILES;
}
else
pFFirstAck->rc = ERROR_FILE_NOT_FOUND;
}
else if (pDir = opendir (NATIVEPath))
{
/* Open the directory and return the handle to Windows */
while (pFFirst->ulRetBufLen - (MAX_PATH + 1) >= pFFirstAck->ulRetBufLen)
{
/* Get as many files as our buffer size will allow */
pffInfo = (fs_findfileinfo *)(((char *)&pFFirstAck->FindFiles) + pFFirstAck->ulRetBufLen);
if (!(pFFirstAck->rc = (short)ReadDirEntry (pDir,
pffInfo,
NATIVEPath,
pSearchPattern,
isRoot)))
{
pFFirstAck->sNumberOfFiles++;
pFFirstAck->ulRetBufLen += sizeof(fs_findfileinfo) +
pffInfo->sFileNameLen - sizeof(pffInfo->FileName);
pffInfo->sFileNameLen = htons(pffInfo->sFileNameLen);
}
else if (pFFirstAck->rc != ERROR_FILE_NOT_FOUND)
break;
}
}
else
{
!fDebug ? 0 : printf ("Can't find/open file/directory - Path = %s\n", NATIVEPath);
pFFirstAck->rc = MapWindowsError (errno);
}
}
pFFirstAck->iFindContext = (int)pDir;
/* Write the Ack struct to Windows. We subtract the length of the array
already included in fs_findfileinfo */
usWriteLen = sizeof(fs_findfirstfileAck) + pFFirstAck->ulRetBufLen;
pFFirstAck->usLen = htons(usWriteLen);
pFFirstAck->ulKey = pFFirst->ulKey;
pFFirstAck->usType = htons(pFFirst->usType);
pFFirstAck->rc = htons(pFFirstAck->rc);
pFFirstAck->sNumberOfFiles = htons(pFFirstAck->sNumberOfFiles);
pFFirstAck->ulRetBufLen = htonl(pFFirstAck->ulRetBufLen);
writen (sockfd, pFFirstAck, usWriteLen);
!fDebug ? 0 : printf ("FS_FINDFIRSTFILE: rc=%d, FilesFound=%d\n",
ntohs(pFFirstAck->rc),
ntohs(pFFirstAck->sNumberOfFiles));
}
/*
* fsFindNextFile
*/
void fsFindNextFile (sockfd, pInBuff)
int sockfd;
char *pInBuff;
{
fs_findnextfile *pFNext;
fs_findnextfileAck *pFNextAck;
fs_findfileinfo *pffInfo;
char *pSearchPattern=0;
int isRoot=FALSE;
char NATIVEPath[MAX_PATH + 1];
USHORT usWriteLen;
pFNext = (fs_findnextfile *)pInBuff;
pFNext->ulRetBufLen = ntohl(pFNext->ulRetBufLen);
pFNext->sPathLen = ntohs(pFNext->sPathLen);
pFNext->ulFlags &= ~FILE_FLAG_KEEP_CASE;
!fDebug ? 0 : printf ("FS_FINDNEXTFILE: Flags=%x, SearchHandle=%d, BuffLen=%d, Path=%s\n",
pFNext->ulFlags, pFNext->iFindHandle, pFNext->ulRetBufLen, pFNext->Path);
pFNextAck = (fs_findnextfileAck *)OutBuff;
memset ((char *)pFNextAck, 0, sizeof(fs_findnextfileAck));
if (pFNext->ulFlags & FILE_FLAG_WILDCARDS || pFNext->ulFlags & FILE_FLAG_HAS_STAR)
{
/* This is a search pattern - strip it */
/* !fDebug ? 0 : printf ("Found wildcard chars\n"); */
pSearchPattern = StripFileFromPath (pFNext->Path, WindowsBSlash);
if (!pFNext->Path[0])
isRoot = TRUE;
}
if (!(pFNextAck->rc = MakeNativePath (pFNext->Path, NATIVEPath, pFNext->ulFlags)))
{
while (pFNext->ulRetBufLen - (MAX_PATH + 1) >= pFNextAck->ulRetBufLen)
{
/* Get as many files as our buffer size will allow */
pffInfo = (fs_findfileinfo *)(((char *)&pFNextAck->FindFiles) + pFNextAck->ulRetBufLen);
if (!(pFNextAck->rc = (short)ReadDirEntry ((DIR *)pFNext->iFindHandle,
pffInfo,
NATIVEPath,
pSearchPattern,
isRoot)))
{
pFNextAck->sNumberOfFiles++;
pFNextAck->ulRetBufLen += (sizeof(fs_findfileinfo) +
pffInfo->sFileNameLen - sizeof(pffInfo->FileName));
pffInfo->sFileNameLen = htons(pffInfo->sFileNameLen);
}
else
break;
}
}
else
pFNextAck->rc = ERROR_NO_MORE_FILES;
usWriteLen = sizeof(fs_findnextfileAck) + pFNextAck->ulRetBufLen;
pFNextAck->usLen = htons(usWriteLen);
pFNextAck->ulKey = pFNext->ulKey;
pFNextAck->usType = htons(pFNext->usType);
pFNextAck->rc = htons(pFNextAck->rc);
pFNextAck->sNumberOfFiles = htons(pFNextAck->sNumberOfFiles);
pFNextAck->ulRetBufLen = htonl(pFNextAck->ulRetBufLen);
writen (sockfd, pFNextAck, usWriteLen);
!fDebug ? 0 : printf ("FS_FINDNEXTFILE: rc=%d, FilesFound=%d\n",
ntohs(pFNextAck->rc),
ntohs(pFNextAck->sNumberOfFiles));
}
/*
* ReadDirEntry
*/
int ReadDirEntry (pDir, pFFileInfo, pPath, pSearchPattern, isRoot)
DIR *pDir;
fs_findfileinfo *pFFileInfo;
char *pPath;
char *pSearchPattern;
int isRoot;
{
struct dirent *pDirEnt;
char NewPath[MAX_PATH];
int fMatched = TRUE, rc, len;
isRoot = TRUE;
memset ((char *)pFFileInfo, 0, sizeof(fs_findfileinfo));
if (pDirEnt = readdir (pDir))
{
if (isRoot && (!strncmp(pDirEnt->d_name, ".", 1) || !strncmp(pDirEnt->d_name, "..", 2)))
fMatched = FALSE;
else if (pSearchPattern)
fMatched = MetaMatch (pSearchPattern, pDirEnt->d_name);
if (fMatched)
{
len = strlen(pDirEnt->d_name) + 1; /* Add one for the NULL */
/* Pad to 4 byte boundries for pointer alignment sensitive machines */
len += 4 - len%4;
pFFileInfo->sFileNameLen = len;
/*
printf("pFFileInfo->sFileNameLen=%d\n", pFFileInfo->sFileNameLen);
fflush(stdout);
*/
strcpy (pFFileInfo->FileName, pDirEnt->d_name);
strcpy (NewPath, pPath);
if (strcmp(NewPath, "/"))
strcat (NewPath, "/");
strcat (NewPath, pDirEnt->d_name);
/*
!fDebug ? 0 : printf ("Found file - pattern=%s, name=%s, NewPath=%s\n",
pSearchPattern, pDirEnt->d_name, NewPath);
fflush(stdout);
*/
if (rc = FillFileStatus (NewPath, pFFileInfo))
return rc;
}
else
{
return ERROR_FILE_NOT_FOUND;
}
}
else
{
/* !fDebug ? 0 : printf ("readdir failed - handle = %d\n", pDir); */
return ERROR_NO_MORE_FILES;
}
return 0;
}
/*
* FillFileStatus
*/
int FillFileStatus (pPath, pFFInfo)
char *pPath;
fs_findfileinfo *pFFInfo;
{
struct stat fStat;
if (!(stat (pPath, &fStat)))
{
/* !fDebug ? 0 : printf ("stat on %s\n", pPath); */
pFFInfo->ulAttrib = 0;
if (fStat.st_mode & S_IRUSR && !(fStat.st_mode & S_IWUSR))
pFFInfo->ulAttrib |= FILE_ATTRIBUTE_READONLY;
if (S_ISDIR(fStat.st_mode))
{
pFFInfo->ulAttrib |= FILE_ATTRIBUTE_DIRECTORY;
}
pFFInfo->ulAttrib = htonl(pFFInfo->ulAttrib);
pFFInfo->tCreate = htonl(fStat.st_mtime);
pFFInfo->tLastAccess = htonl(fStat.st_atime);
pFFInfo->tLastWrite = htonl(fStat.st_mtime);
pFFInfo->ulFileSize = htonl(fStat.st_size);
}
else
{
!fDebug ? 0 : printf ("stat failed on %s\n", pPath);
fflush(stdout);
return MapWindowsError (errno);
}
return 0;
}
/*
* fsFindClose
*/
void fsFindClose (sockfd, pInBuff)
int sockfd;
char *pInBuff;
{
fs_findclose *pFindClose;
fs_findcloseAck *pFindCloseAck;
pFindClose = (fs_findclose *)pInBuff;
!fDebug ? 0 : printf ("FS_FINDCLOSE: Handle=%d\n", pFindClose->iFindHandle);
pFindCloseAck = (fs_findcloseAck *)OutBuff;
memset ((char *)pFindCloseAck, 0, sizeof(fs_findcloseAck));
/* No find handle for single file finds */
if (pFindClose->iFindHandle)
if (closedir ((DIR *)pFindClose->iFindHandle) < 0)
pFindCloseAck->rc = htons(MapWindowsError(errno));
pFindCloseAck->usLen = htons(sizeof(fs_findcloseAck));
pFindCloseAck->ulKey = pFindClose->ulKey;
pFindCloseAck->usType = htons(pFindClose->usType);
writen (sockfd, pFindCloseAck, sizeof(fs_findcloseAck));
!fDebug ? 0 : printf ("FS_FINDCLOSE: rc=%d\n", ntohs(pFindCloseAck->rc));
}
/*
* fsFileAttributes
*/
void fsFileAttributes (sockfd, pInBuff)
int sockfd;
char *pInBuff;
{
fs_fileattributes *pFileAttrib;
fs_fileattributesAck *pFileAttribAck;
struct stat fStat;
struct utimbuf uTime;
char NATIVEPath[MAX_PATH + 1];
pFileAttrib = (fs_fileattributes *)pInBuff;
pFileAttrib->ulAttribs = ntohl(pFileAttrib->ulAttribs);
pFileAttrib->NativeTime = ntohl(pFileAttrib->NativeTime);
pFileAttrib->sPathLen = ntohs(pFileAttrib->sPathLen);
!fDebug ? 0 : printf ("FS_FILEATTRIBUTES: Flags=%x, Attribs=%x, Time=%x, Path=%s\n",
pFileAttrib->ulFlags, pFileAttrib->ulAttribs, pFileAttrib->NativeTime, pFileAttrib->Path);
pFileAttribAck = (fs_fileattributesAck *)OutBuff;
memset ((char *)pFileAttribAck, 0, sizeof(fs_fileattributesAck));
if (pFileAttribAck->rc = MakeNativePath (pFileAttrib->Path, NATIVEPath, pFileAttrib->ulAttribs))
{}
else if (!(pFileAttribAck->rc = stat(NATIVEPath, &fStat)))
{
uTime.actime = fStat.st_atime;
uTime.modtime = fStat.st_mtime;
/* What does windows want us to do? */
switch (pFileAttrib->ulFlags)
{
case GET_ATTRIBUTES:
{
!fDebug ? 0 : printf ("GET_ATTRIBUTES - mode=%o\n", fStat.st_mode);
if (S_ISDIR(fStat.st_mode))
pFileAttribAck->ulAttribs |= FILE_ATTRIBUTE_DIRECTORY;
if ((fStat.st_mode & S_IRUSR) && !(fStat.st_mode & S_IWUSR))
pFileAttribAck->ulAttribs |= FILE_ATTRIBUTE_READONLY;
break;
}
case SET_ATTRIBUTES:
{
mode_t mode;
!fDebug ? 0 : printf ("SET_ATTRIBUTES - mode=%o\n", fStat.st_mode);
if (pFileAttrib->ulAttribs & FILE_ATTRIBUTE_READONLY)
mode = ulDefaultAttributes & ~(S_IWUSR | S_IWGRP | S_IWOTH);
else
mode = ulDefaultAttributes;
if (chmod (NATIVEPath, mode) < 0)
pFileAttribAck->rc = MapWindowsError (errno);
break;
}
case GET_ATTRIB_COMP_FILESIZE:
{
!fDebug ? 0 : printf ("GET_ATTRIB_COMP_FILESIZE\n");
pFileAttribAck->ulFileSize = fStat.st_size;
break;
}
case GET_ATTRIB_MODIFY_DATETIME:
{
!fDebug ? 0 : printf ("GET_ATTRIB_MODIFY_DATETIME\n");
pFileAttribAck->NativeTime = fStat.st_mtime;
break;
}
case SET_ATTRIB_MODIFY_DATETIME:
{
!fDebug ? 0 : printf ("SET_ATTRIB_MODIFY_DATETIME\n");
uTime.modtime = pFileAttrib->NativeTime;
if (utime (NATIVEPath, &uTime) < 0)
pFileAttribAck->rc = MapWindowsError (errno);
break;
}
case GET_ATTRIB_LAST_ACCESS_DATETIME:
{
!fDebug ? 0 : printf ("GET_ATTRIB_LAST_ACCESS_DATETIME\n");
pFileAttribAck->NativeTime = fStat.st_atime;
break;
}
case SET_ATTRIB_LAST_ACCESS_DATETIME:
{
!fDebug ? 0 : printf ("SET_ATTRIB_LAST_ACCESS_DATETIME\n");
uTime.actime = pFileAttrib->NativeTime;
if (utime (NATIVEPath, &uTime) < 0)
pFileAttribAck->rc = MapWindowsError (errno);
break;
}
case GET_ATTRIB_CREATION_DATETIME:
{
!fDebug ? 0 : printf ("GET_ATTRIB_CREATION_DATETIME\n");
pFileAttribAck->NativeTime = fStat.st_mtime;
break;
}
case SET_ATTRIB_CREATION_DATETIME:
{
!fDebug ? 0 : printf ("SET_ATTRIB_CREATION_DATETIME\n");
uTime.modtime = pFileAttrib->NativeTime;
if (utime (NATIVEPath, &uTime) < 0)
pFileAttribAck->rc = MapWindowsError (errno);
break;
}
default:
!fDebug ? 0 : printf ("File Attributes: ERROR! Unknown Type=%d\n", pFileAttrib->ulFlags);
}
}
else
{
pFileAttribAck->rc = MapWindowsError (errno);
!fDebug ? 0 : printf ("fsFileAttributes: Stat failed on %s\n", NATIVEPath);
}
pFileAttribAck->usLen = htons(sizeof(fs_fileattributesAck));
pFileAttribAck->ulKey = pFileAttrib->ulKey;
pFileAttribAck->usType = htons(pFileAttrib->usType);
pFileAttribAck->ulAttribs = htonl(pFileAttribAck->ulAttribs);
pFileAttribAck->NativeTime = htonl(pFileAttribAck->NativeTime);
pFileAttribAck->ulFileSize = htonl(pFileAttribAck->ulFileSize);
pFileAttribAck->rc = htons(pFileAttribAck->rc);
writen (sockfd, pFileAttribAck, sizeof(fs_fileattributesAck));
!fDebug ? 0 : printf ("FS_FILEATTRIBUTES: rc=%d, attrib=%x\n",
ntohs(pFileAttribAck->rc), ntohl(pFileAttribAck->ulAttribs));
}
/*
* fsDir
*/
void fsDir (sockfd, pInBuff)
int sockfd;
char *pInBuff;
{
fs_dir *pDir;
fs_dirAck *pDirAck;
struct stat fStat;
char NATIVEPath[MAX_PATH];
ULONG ulDirAttribs=ulDefaultAttributes;
pDir = (fs_dir *)pInBuff;
pDir->ulAttribs = ntohl(pDir->ulAttribs);
pDir->sPathLen = ntohs(pDir->sPathLen);
!fDebug ? 0 : printf ("FS_DIR: Flags=%x, Path=%s\n", pDir->ulFlags, pDir->Path);
pDirAck = (fs_dirAck *)OutBuff;
memset ((char *)pDirAck, 0, sizeof(fs_dirAck));
pDirAck->rc = MakeNativePath (pDir->Path, NATIVEPath, pDir->ulAttribs);
if (!pDirAck->rc)
{
switch (pDir->ulFlags)
{
case CREATE_DIR:
{
if (ulDefaultAttributes & S_IRUSR)
ulDirAttribs |= S_IXUSR;
if (ulDefaultAttributes & S_IRGRP)
ulDirAttribs |= S_IXGRP;
if (ulDefaultAttributes & S_IROTH)
ulDirAttribs |= S_IXOTH;
!fDebug ? 0 : printf ("CREATE_DIR: %s\n", NATIVEPath);
if (mkdir(NATIVEPath, ulDirAttribs) < 0)
pDirAck->rc = MapWindowsError (errno);
break;
}
case DELETE_DIR:
{
!fDebug ? 0 : printf ("DELETE_DIR: %s\n", NATIVEPath);
if (rmdir(NATIVEPath) < 0)
pDirAck->rc = MapWindowsError (errno);
break;
}
case QUERY83_DIR:
{
!fDebug ? 0 : printf ("QUERY83_DIR: %s\n", NATIVEPath);
pDirAck->rc = ERROR_INVALID_FUNCTION;
break;
}
case QUERYLONG_DIR:
{
!fDebug ? 0 : printf ("QUERYLONG_DIR: %s\n", NATIVEPath);
pDirAck->rc = ERROR_INVALID_FUNCTION;
break;
}
case CHECK_DIR:
{
!fDebug ? 0 : printf ("CHECK_DIR: %s\n", NATIVEPath);
if (!(stat (NATIVEPath, &fStat)))
{
if (S_ISDIR(fStat.st_mode))
{
!fDebug ? 0 : printf ("Found Valid Directory\n");
pDirAck->rc = 0;
}
else
pDirAck->rc = ERROR_FILE_NOT_FOUND;
}
else
pDirAck->rc = MapWindowsError (errno);
break;
}
default:
!fDebug ? 0 : printf ("FsDir: ERROR_INVALID_FUNCTION!!!!\n");
pDirAck->rc = ERROR_INVALID_FUNCTION;
}
}
else
pDirAck->rc = ERROR_PATH_NOT_FOUND;
pDirAck->usLen = htons(sizeof(fs_dirAck));
pDirAck->ulKey = pDir->ulKey;
pDirAck->usType = htons(pDir->usType);
pDirAck->rc = htons(pDirAck->rc);
writen (sockfd, pDirAck, sizeof(fs_dirAck));
!fDebug ? 0 : printf ("FS_DIR: rc=%d\n", ntohs(pDirAck->rc));
}
/*
* fsDeleteFile
*/
void fsDeleteFile (sockfd, pInBuff)
int sockfd;
char *pInBuff;
{
fs_deletefile *pDelete;
fs_deletefileAck *pDeleteAck;
DIR *pDir;
struct dirent *pDirEnt = 0;
int fDeleted=FALSE;
char NATIVEPath[MAX_PATH];
char DeletePath[MAX_PATH];
struct stat fStat;
pDelete = (fs_deletefile *)pInBuff;
pDelete->sPathLen = ntohs(pDelete->sPathLen);
!fDebug ? 0 : printf ("FS_DELETEFILE: Attribs=%x, Path=%s\n",
pDelete->ulAttribs, pDelete->Path);
pDeleteAck = (fs_deletefileAck *)OutBuff;
memset ((char *)pDeleteAck, 0, sizeof(fs_deletefileAck));
if (!(pDeleteAck->rc = MakeNativePath (pDelete->Path, NATIVEPath, pDelete->ulAttribs)))
{
if (!(stat(NATIVEPath, &fStat)))
{
if (!(fStat.st_mode & S_IWUSR))
{
/* Readonly */
pDeleteAck->rc = ERROR_ACCESS_DENIED;
}
else if (!S_ISDIR(fStat.st_mode))
{
/* Delete a single file */
!fDebug ? 0 : printf ("FS_DELETEFILE: Single file delete\n");
if (unlink(NATIVEPath) < 0)
{
pDeleteAck->rc = MapWindowsError (errno);
!fDebug ? 0 : printf ("FS_DELETEFILE: fail - rc = %d\n", errno);
}
else
pDeleteAck->rc = 0;
}
else
{
!fDebug ? 0 : printf ("FS_DELETEFILE: Directory delete\n");
/* Delete the whole directory */
if (pDir = opendir (NATIVEPath))
{
while (pDirEnt = readdir (pDir))
{
if (!strncmp(pDirEnt->d_name, ".", 1) || !strncmp(pDirEnt->d_name, "..", 2))
continue;
strcpy (DeletePath, NATIVEPath);
strcat (DeletePath, "/");
strcat (DeletePath, pDirEnt->d_name);
if (unlink(DeletePath) < 0)
{
pDeleteAck->rc = MapWindowsError (errno);
break;
}
else
fDeleted = TRUE;
}
closedir (pDir);
if (!fDeleted)
pDeleteAck->rc = ERROR_FILE_NOT_FOUND;
}
else
pDeleteAck->rc = ERROR_FILE_NOT_FOUND;
}
}
else
pDeleteAck->rc = ERROR_FILE_NOT_FOUND;
}
pDeleteAck->usLen = htons(sizeof(fs_deletefileAck));
pDeleteAck->ulKey = pDelete->ulKey;
pDeleteAck->usType = htons(pDelete->usType);
pDeleteAck->rc = htons(pDeleteAck->rc);
writen (sockfd, pDeleteAck, sizeof(fs_deletefileAck));
!fDebug ? 0 : printf ("FS_DELETEFILE: rc=%d\n", ntohs(pDeleteAck->rc));
}
/*
* fsRenameFile
*/
void fsRenameFile (sockfd, pInBuff)
int sockfd;
char *pInBuff;
{
fs_renamefile *pRename;
fs_renamefileAck *pRenameAck;
char NATIVEPath1[MAX_PATH];
char NATIVEPath2[MAX_PATH];
pRename = (fs_renamefile *)pInBuff;
pRename->sPathLen1 = ntohs(pRename->sPathLen1);
pRename->sPathLen2 = ntohs(pRename->sPathLen2);
!fDebug ? 0 : printf ("FS_RENAMEFILE: Attribs=%x, From=%s, To=%s\n",
pRename->ulAttribs, pRename->Paths, &pRename->Paths[pRename->sPathLen1]);
pRenameAck = (fs_renamefileAck *)OutBuff;
memset ((char *)pRenameAck, 0, sizeof(fs_renamefileAck));
if (!(pRenameAck->rc = MakeNativePath (pRename->Paths, NATIVEPath1, 0)))
{
pRenameAck->rc = MakeNativePath (&pRename->Paths[pRename->sPathLen1], NATIVEPath2, pRename->ulAttribs);
if (!pRenameAck->rc)
{
if (rename(NATIVEPath1, NATIVEPath2) < 0)
pRenameAck->rc = MapWindowsError (errno);
}
}
else
pRenameAck->rc = ERROR_PATH_NOT_FOUND;
pRenameAck->usLen = htons(sizeof(fs_renamefileAck));
pRenameAck->ulKey = pRename->ulKey;
pRenameAck->usType = htons(pRename->usType);
pRenameAck->rc = htons(pRenameAck->rc);
writen (sockfd, pRenameAck, sizeof(fs_renamefileAck));
!fDebug ? 0 : printf ("FS_RENAMEFILE: rc=%d\n", ntohs(pRenameAck->rc));
}
/*
* fsGetDiskInfo
*/
void fsGetDiskInfo (sockfd, pInBuff)
int sockfd;
char *pInBuff;
{
fs_getdiskinfo *pGetDiskInfo;
fs_getdiskinfoAck *pGetDiskInfoAck;
ULONG ulFileCount=0;
/* Walk the tree starting from the directory where we were
started and not exceeding MAX readdir count */
pGetDiskInfo = (fs_getdiskinfo *)pInBuff;
!fDebug ? 0 : printf ("FS_GETDISKINFO: Starting Tree Walk...\n");
pGetDiskInfoAck = (fs_getdiskinfoAck *)OutBuff;
memset ((char *)pGetDiskInfoAck, 0, sizeof(fs_getdiskinfoAck));
ProcessDir (HomePath, &pGetDiskInfoAck->ulDiskSpaceUsedBytes, &ulFileCount);
if (ulFileCount >= ulMaxReaddirs)
pGetDiskInfoAck->ulDiskSpaceUsedBytes = 0;
pGetDiskInfoAck->usLen = htons(sizeof(fs_getdiskinfoAck));
pGetDiskInfoAck->ulKey = pGetDiskInfo->ulKey;
pGetDiskInfoAck->usType = htons(pGetDiskInfo->usType);
pGetDiskInfoAck->ulDiskSpaceUsedBytes = htonl(pGetDiskInfoAck->ulDiskSpaceUsedBytes);
pGetDiskInfoAck->rc = htons(pGetDiskInfoAck->rc);
writen (sockfd, pGetDiskInfoAck, sizeof(fs_getdiskinfoAck));
!fDebug ? 0 : printf ("FS_GETDISKINFO: rc=%d, DiskSize=%d\n",
ntohs(pGetDiskInfoAck->rc),
ntohl(pGetDiskInfoAck->ulDiskSpaceUsedBytes));
}
/*
* ProcessDir
*/
void ProcessDir (pPath, pulDiskSpace, pulFileCount)
char *pPath;
ULONG *pulDiskSpace;
ULONG *pulFileCount;
{
DIR *pCurrDir;
struct dirent *pDirEntry;
struct stat Status;
char Cwd[MAX_PATH];
if (pCurrDir = opendir (pPath))
{
if (getcwd (Cwd,MAX_PATH))
{
if (!chdir(pPath))
{
while (pDirEntry = readdir (pCurrDir))
{
if (!stat(pDirEntry->d_name, &Status))
{
*pulDiskSpace += Status.st_size;
(*pulFileCount)++;
/*
!fDebug ? 0 : printf ("ProcessDir: File=%s, Total Size=%d, Count=%d\n",
pDirEntry->d_name, *pulDiskSpace, *pulFileCount);
*/
if (*pulFileCount >= ulMaxReaddirs)
break;
if (strcmp(pDirEntry->d_name, "."))
{
if (strcmp(pDirEntry->d_name, ".."))
{
if (S_ISDIR(Status.st_mode))
{
ProcessDir (pDirEntry->d_name, pulDiskSpace, pulFileCount);
}
}
}
}
}
}
chdir (Cwd);
}
closedir (pCurrDir);
}
}
/*****************************************************
UTILITIES
******************************************************/
/*
* MakeNativePath
*/
int MakeNativePath (pInPath, pOutPath, ulAttrib)
char *pInPath;
char *pOutPath;
ULONG ulAttrib;
{
char *p;
int i, rc=0;
char TempInPath[MAX_PATH];
char TempOutPath[MAX_PATH];
char LastElement[MAX_PATH];
char *pLastElement;
/* !fDebug ? 0 : printf ("MakeNativePath - InPath = %s\n", pInPath); */
if (!pInPath)
return 0;
if (!pInPath[0])
{
strcpy (pOutPath, HomePath);
return 0;
}
if (ulAttrib & FILE_FLAG_KEEP_CASE)
{
!fDebug ? 0 : printf ("MakeNativePath - FILE_FLAG_KEEP_CASE set\n");
/* If we are keeping the last element case sensitive, there is
no need to map it to the server. Strip it now and add back later */
if (pLastElement = StripFileFromPath (pInPath, WindowsBSlash))
strcpy (LastElement, pLastElement);
else
LastElement[0] = 0;
}
strcpy (TempOutPath, HomePath);
if (pInPath[0])
{
/* Convert all the '\' to '/' */
for (i=0, p=pInPath; i<strlen(pInPath); i++, p++)
{
if (*p == WindowsBSlash)
*p = NativeSlash;
}
strcpy (TempInPath, pInPath);
/* Parse the path (if any) and make sure we can find
all the sub-dirs in UPPERCASE for Windows */
if (p = strtok (TempInPath, NativeSlashStr))
{
if (!(rc = CaseMatchDirectory (p, TempOutPath)))
{
/* !fDebug ? 0 : printf ("MakeNativePath - adding: %s\n", TempOutPath); */
while (p = strtok (NULL, NativeSlashStr))
{
if (rc = CaseMatchDirectory (p, TempOutPath))
break;
/* !fDebug ? 0 : printf ("MakeNativePath - adding: %s\n", TempOutPath); */
}
}
}
}
strcpy (pOutPath, TempOutPath);
/* Put back any case sensitive elements */
if (ulAttrib & FILE_FLAG_KEEP_CASE)
{
if (LastElement[0])
{
if (strcmp(pOutPath, "/"))
strcat (pOutPath, "/");
strcat (pOutPath, LastElement);
}
}
/* !fDebug ? 0 : printf ("MakeNativePath - OutPath = %s\n", pOutPath); */
return rc;
}
/*
* CaseMatchDirectory
*/
int CaseMatchDirectory (pFile, pPath)
char *pFile;
char *pPath;
{
DIR *pDir;
struct dirent *pDirEnt = 0;
char TempFile[MAX_PATH];
if (pDir = opendir (pPath))
{
while (pDirEnt = readdir (pDir))
{
strcpy (TempFile, pDirEnt->d_name);
if (!(strcmp(zstrupr(pFile), zstrupr(TempFile))))
{
/* We found the directory/file. Add it to path */
if (strcmp(pPath, "/"))
strcat (pPath, "/");
/* !fDebug ? 0 : printf ("CaseMatchDirectory: Found = %s\n", pDirEnt->d_name); */
strcat (pPath, pDirEnt->d_name);
closedir (pDir);
return 0;
}
}
}
else
{
!fDebug ? 0 : printf ("CaseMatchDirectory - Can't open dir: %s, File: %s\n", pPath, pFile);
return MapWindowsError (errno);
}
closedir (pDir);
return ERROR_FILE_NOT_FOUND;
}
/*
* zstrupr
*/
char *zstrupr (pString)
char *pString;
{
char *p = pString;
while (*p)
{
if (*p >= 'a' && *p <= 'z')
*p -= 32;
p++;
}
return pString;
}
#define STAR_DOT_STAR "*.*"
#define STAR_DOT "*."
#define LONE_STAR "*"
/*
* MetaMatch - Warning! You must convert to a native path before using this routine.
* Also, you don't need to call this routine unless the FILE_FLAG_HAS_STAR
* flag is set in the FS_FINDFIRSTFILE, FS_RENAMEFILE, and FS_DELETEFILE
* file system calls.
*
* Note: Even with long filenames Windows 95 still supports "*.*" and "*." in
* the old 8.3 fashion.
*
*
*/
int MetaMatch (pWindowsFile, pNativeFile)
char *pWindowsFile;
char *pNativeFile;
{
char tmpWindowsPattern[MAX_PATH];
char tmpNativeFile[MAX_PATH];
int rc;
/* In Windows long file name support the meta-character '*' indicates
0 or more characters and '?' indicates one character. You can have
multiple '*' and '?' */
/* printf ("MetaMatch File=%s, Path=%s\n", pWindowsFile, pNativeFile); */
if (pWindowsFile[0] == 0)
return FALSE;
strcpy (tmpWindowsPattern, pWindowsFile);
strcpy (tmpNativeFile, pNativeFile);
zstrupr (tmpWindowsPattern);
zstrupr (tmpNativeFile);
/* No path names at this point */
if (strrchr (tmpWindowsPattern, NativeSlash))
return FALSE;
/* Handle special Windows case: "*.*", "*." and regular "*" */
if (!(strcmp(tmpWindowsPattern, LONE_STAR)))
return TRUE; /* This was a "*" */
if (!(strcmp(tmpWindowsPattern, STAR_DOT_STAR)))
return TRUE; /* This was a "*.*" */
rc = CheckForExtension (pNativeFile);
if (!(strcmp(tmpWindowsPattern, STAR_DOT)))
return rc ? FALSE : TRUE; /* This was a "*." */
if (!rc) /* If no extension */
{
/* Handle "<pattern>.*" case for files without extensions */
NukeDotStar (tmpWindowsPattern);
}
return MatchStarsAndQMs (tmpWindowsPattern, tmpNativeFile);
}
/*
* MatchStarsAndQMs
*/
int MatchStarsAndQMs (pPattern, pNativeFile)
char *pPattern;
char *pNativeFile;
{
char *pP=pPattern, *pF=pNativeFile;
/*
printf ("MatchStarsAndQMs - pPattern=%s, pNativeFile=%s\n",
pPattern, pNativeFile);
*/
while (*pF && *pP) /* Scan through file name */
{
if (*pP == '?')
{
pP++; pF++;
}
else if (*pP == '*')
{
pP++;
if (*pP == 0)
return TRUE;
if (*pP == '*')
{
pP++;
if (*pP == 0)
return TRUE;
}
if (!(FindSubPattern (pP, pF, &pP, &pF)))
pP--;
else if (*pP == 0 && *pF != 0)
return FALSE;
}
else if (*pP == *pF)
{
pP++; pF++;
}
else if (*pP != *pF)
{
return FALSE;
}
}
if (*pP)
return FALSE;
return TRUE;
}
/*
* FindSubPattern
*/
int FindSubPattern (pSubPat, pSubFile, pPatOut, pFileOut)
char *pSubPat;
char *pSubFile;
char **pPatOut;
char **pFileOut;
{
char *pSubTmp = pSubPat;
/* printf ("FindSubPattern - pSubPat=%s, pSubFile=%s\n", pSubPat, pSubFile); */
while (*pSubPat && *pSubFile)
{
/* Compare up to next '*' skip any '?' */
if (*pSubPat == '*')
{
*pPatOut = pSubPat;
*pFileOut = pSubFile;
return TRUE;
}
if (*pSubPat == '?')
{
pSubPat++;
}
else if (*pSubPat == *pSubFile)
{
pSubPat++;
}
else
pSubPat = pSubTmp;
pSubFile++;
}
*pFileOut = pSubFile;
if (*pSubPat == 0 && *pSubFile)
return FALSE;
if (*pSubPat)
return TRUE;
*pPatOut = pSubPat;
return TRUE;
}
/*
* CheckForExtension
*/
int CheckForExtension (pFile)
char *pFile;
{
char *p;
int i;
/* This was a "*." If any of the last four characters is a '.'
we consider this a file with an 8.3 extenstion. Windows uses
"*." to indicate files with no extension. */
p = &pFile[strlen(pFile)-1]; /* Last char in string */
for (i=0; i<4; i++, p--)
{
if (*p == '.')
return TRUE;
}
return FALSE;
}
/*
* NukeDotStar
*/
void NukeDotStar (pPattern)
char *pPattern;
{
if (strlen(pPattern) >= 2)
{
if (pPattern[strlen(pPattern)-1] == '*')
{
if (pPattern[strlen(pPattern)-2] == '.')
{
pPattern[strlen(pPattern)-2] = 0;
}
}
}
}
/*
* StripFileFromPath - Puts a NULL in the last '\' and return ptr
* to the file or search.
*/
char *StripFileFromPath (pPath, SlashType)
char *pPath;
char SlashType;
{
char *p;
/* Get the file name from the full Windows path. Windows ALWAYS provides
a full path starting with '\' */
if (!(p = strrchr (pPath, SlashType)))
return 0;
*p = 0;
return p+1;
}
/*
* Read "n" bytes from a stream socket
*/
int readn (fd, ptr, nbytes)
int fd;
char *ptr;
int nbytes;
{
int nleft, nread;
nleft = nbytes;
while (nleft > 0)
{
nread = read (fd, ptr, nleft);
if (nread < 0)
{
!fDebug ? 0 : printf ("%s File Error: read(), rc = %d\n", ProgramName, nread);
return nread;
}
else if (nread == 0)
break; /* EOF */
nleft -= nread;
ptr += nread;
}
return (nbytes - nleft); /* return >= 0 */
}
/*
* Write "n" bytes to a stream socket
*/
int writen (fd, ptr, nbytes)
int fd;
char *ptr;
int nbytes;
{
int nleft, nwritten;
nleft = nbytes;
while (nleft > 0)
{
nwritten = write (fd, ptr, nleft);
if (nwritten <= 0) /* error */
{
!fDebug ? 0 : printf ("%s File Error: write(), rc = %d\n", ProgramName, nwritten);
return nwritten;
}
nleft -= nwritten;
ptr += nwritten;
}
return (nbytes - nleft);
}
/*
* MapWindowsError
*/
USHORT MapWindowsError (usPosixErr)
USHORT usPosixErr;
{
if (usPosixErr > MAX_ERRORS)
return usPosixErr;
return WindowsErrors[usPosixErr];
}
/*
* SetFilePosition
*/
int SetFilePosition (iFileDesc, lNewPos)
int iFileDesc;
long lNewPos;
{
struct stat fStat;
long lPosition;
/* Get the length of this file */
if (fstat(iFileDesc, &fStat) < 0)
return MapWindowsError(errno);
/* Make sure we are within the file */
if (lNewPos > fStat.st_size)
return ERROR_ACCESS_DENIED;
/* Seek the file to new location */
if ((lPosition = lseek (iFileDesc, lNewPos, SEEK_SET)) < 0)
{
!fDebug ? 0 : printf ("SetFilePosition: lseek failed, errno=%d, lPosition=%d, iFileDesc=%d, lNewPos=%d\n",
errno, lPosition, iFileDesc, lNewPos);
return MapWindowsError(errno);
}
if (lPosition != lNewPos)
return ERROR_ACCESS_DENIED;
return 0;
}